/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.thesis.algorithm;

import java.util.*;


/**
 * 
 * @author Administrator
 */
public class HMMMatrices {

	// hashtable <currState, hashtable<prevState, Integer>>
	Hashtable<Character, Hashtable<Character, Integer>> stateTransitionCount = new Hashtable<Character, Hashtable<Character, Integer>>();
	// hashtable <observation, hashtable<state, Integer>>
	Hashtable<Character, Hashtable<Character, Integer>> observationSTStateCount = new Hashtable<Character, Hashtable<Character, Integer>>();
	Hashtable<Character, Integer> firstStateCount = new Hashtable<Character, Integer>();
	Hashtable<Character, Integer> stateCount = new Hashtable<Character, Integer>();
	Hashtable<Character, Integer> lastStateCount = new Hashtable<Character, Integer>();
	int numberOfAddedSequence = 0;

	public void emitAll() {
		char currState;
		Set set1 = firstStateCount.keySet();
		Iterator iter1 = set1.iterator();
		while (iter1.hasNext()) {
			currState = (Character) (iter1.next());
			System.out.println("Pi " + currState + " : " + lookupPI(currState));
		}

		Set set2;
		char currobserv;
		Iterator iter2;
		set1 = observationSTStateCount.keySet();
		iter1 = set1.iterator();
		// traversing the states I that has observation
		// input.sequenceinFile.get(i)
		while (iter1.hasNext()) {
			currobserv = (Character) (iter1.next());
			set2 = observationSTStateCount.get(currobserv).keySet();
			iter2 = set2.iterator();
			// traversing the states that can transfer to state I
			while (iter2.hasNext()) {
				currState = (Character) (iter2.next());
				System.out.println("B " + currState + " " + currobserv + " : "
						+ lookupB(currState, currobserv));
			}

		}

		char prevState;
		set1 = stateTransitionCount.keySet();
		iter1 = set1.iterator();
		// traversing the states I that has observation
		// input.sequenceinFile.get(i)
		while (iter1.hasNext()) {
			currState = (Character) (iter1.next());
			set2 = stateTransitionCount.get(currState).keySet();
			iter2 = set2.iterator();
			// traversing the states that can transfer to state I
			while (iter2.hasNext()) {
				prevState = (Character) (iter2.next());
				System.out.println("A " + (int) prevState + " --> " + (int) currState
						+ " : " + lookupA(prevState, currState));
			}

		}

	}
	
	public String toString() {
		String result="";
		
		char currState;
		Set set1 = firstStateCount.keySet();
		Iterator iter1 = set1.iterator();
		while (iter1.hasNext()) {
			currState = (Character) (iter1.next());
			result+=("Pi " + (int)currState + " : " + lookupPI(currState)) +"\n";
		}

		Set set2;
		char currobserv;
		Iterator iter2;
		set1 = observationSTStateCount.keySet();
		iter1 = set1.iterator();
		// traversing the states I that has observation
		// input.sequenceinFile.get(i)
		while (iter1.hasNext()) {
			currobserv = (Character) (iter1.next());
			set2 = observationSTStateCount.get(currobserv).keySet();
			iter2 = set2.iterator();
			// traversing the states that can transfer to state I
			while (iter2.hasNext()) {
				currState = (Character) (iter2.next());
				result+=("B " + (int)currState + " " + (int)currobserv + " : "
						+ lookupB(currState, currobserv))+"\n";
			}

		}

		char prevState;
		set1 = stateTransitionCount.keySet();
		iter1 = set1.iterator();
		// traversing the states I that has observation
		// input.sequenceinFile.get(i)
		while (iter1.hasNext()) {
			currState = (Character) (iter1.next());
			set2 = stateTransitionCount.get(currState).keySet();
			iter2 = set2.iterator();
			// traversing the states that can transfer to state I
			while (iter2.hasNext()) {
				prevState = (Character) (iter2.next());
				result+=("A " + (int)prevState + " --> " + (int) currState
						+ " : " + lookupA(prevState, currState))+"\n";
			}

		}
		
		return result;
	}


	public double lookupAwithEqualChances(char prevState, char nextState) {
		if (stateTransitionCount.containsKey(nextState)
				&& stateTransitionCount.get(nextState).containsKey(prevState)) {
			Enumeration enume = stateTransitionCount.keys();
			int count = 0;
			while (enume.hasMoreElements()) {
				char tmp = (Character) (enume.nextElement());
				if (stateTransitionCount.get(tmp).containsKey(prevState))
					count++;
			}
			return 1 / count;
		}
		return 0;
	}

	public double lookupA(char prevState, char nextState) {
		if (stateTransitionCount.containsKey(nextState)
				&& stateTransitionCount.get(nextState).containsKey(prevState)) {
			if (!lastStateCount.containsKey(prevState))
				return (double) (stateTransitionCount.get(nextState)
						.get(prevState)) / stateCount.get(prevState);
			else
				return (double) (stateTransitionCount.get(nextState)
						.get(prevState))
						/ (stateCount.get(prevState) - lastStateCount
								.get(prevState));
		}
		return 0;
	}

	public double lookupB(char state, char observation) {
		if (observationSTStateCount.containsKey(observation)
				&& observationSTStateCount.get(observation).containsKey(state)) {
			return (double) (observationSTStateCount.get(observation)
					.get(state)) / stateCount.get(state);
		}
		return 0;
	}

	public double lookupPIwithequalchance(char state) {
		return 1.0 / stateCount.size();
	}

	public double lookupPI(char state) {
		// if (firstStateCount.containsKey(state)) {
		// return (double) (firstStateCount.get(state)) / numberOfAddedSequence;
		// }
		// return 0;
		return 1.0 / stateCount.size();

	}

	public void addSequence(Sequence sequence) {
		numberOfAddedSequence++;

		// change a value in matrix by + 1
		SequenceElement first = sequence.sequenceinFile.getFirst();

		// count first state
		if (firstStateCount.containsKey(first.State) == false) {
			firstStateCount.put(first.State, 1);
		} else {
			firstStateCount.put(first.State,
					firstStateCount.get(first.State) + 1);
		}

		// //count first state count
		if (stateCount.containsKey(first.State) == false) {
			stateCount.put(first.State, 1);
		} else {
			stateCount.put(first.State, stateCount.get(first.State) + 1);
		}
		// count observation ST state first
		if (observationSTStateCount.containsKey(first.Observation) == false) {
			Hashtable<Character, Integer> tmp = new Hashtable<Character, Integer>();
			tmp.put(first.State, 1);
			observationSTStateCount.put(first.Observation, tmp);
		} else {
			if (observationSTStateCount.get(first.Observation).containsKey(
					first.State) == false) {
				observationSTStateCount.get(first.Observation).put(first.State,
						1);
			} else {
				int tmp = observationSTStateCount.get(first.Observation).get(
						first.State);
				observationSTStateCount.get(first.Observation).put(first.State,
						tmp + 1);
			}
		}

		SequenceElement prevElement = first;
		SequenceElement currElement = first;
		for (int i = 1; i < sequence.sequenceinFile.size(); ++i) {
			currElement = sequence.sequenceinFile.get(i);

			// =================
			if (observationSTStateCount.containsKey(currElement.Observation) == false) {
				Hashtable<Character, Integer> tmp = new Hashtable<Character, Integer>();
				tmp.put(currElement.State, 1);
				observationSTStateCount.put(currElement.Observation, tmp);
			} else {
				if (observationSTStateCount.get(currElement.Observation)
						.containsKey(currElement.State) == false) {
					observationSTStateCount.get(currElement.Observation).put(
							currElement.State, 1);
				} else {
					int tmp = observationSTStateCount.get(
							currElement.Observation).get(currElement.State);
					observationSTStateCount.get(currElement.Observation).put(
							currElement.State, tmp + 1);
				}
			}

			// =================
			if (stateCount.containsKey(currElement.State)) {
				stateCount.put(currElement.State,
						stateCount.get(currElement.State) + 1);
			} else {
				stateCount.put(currElement.State, 1);
			}

			// =================
			if (stateTransitionCount.containsKey(currElement.State) == false) {
				Hashtable<Character, Integer> tmp = new Hashtable<Character, Integer>();
				tmp.put(prevElement.State, 1);
				stateTransitionCount.put(currElement.State, tmp);
			} else {
				if (stateTransitionCount.get(currElement.State).containsKey(
						prevElement.State) == false) {
					stateTransitionCount.get(currElement.State).put(
							prevElement.State, 1);
				} else {
					int tmp = stateTransitionCount.get(currElement.State).get(
							prevElement.State);
					stateTransitionCount.get(currElement.State).put(
							prevElement.State, tmp + 1);
				}
			}

			// =====================
			prevElement = currElement;
		}

		if (lastStateCount.containsKey(currElement.State) == false) {
			lastStateCount.put(currElement.State, 1);
		} else {
			lastStateCount.put(currElement.State,
					lastStateCount.get(currElement.State) + 1);
		}

	}

	public void reset() {
		stateCount.clear();
		observationSTStateCount.clear();
		firstStateCount.clear();
		stateTransitionCount.clear();
		numberOfAddedSequence = 0;
	}
}
